package com.qfedu.edu.seckill.storageservice.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.qfedu.edu.seckill.bo.OrderShow;
import com.qfedu.edu.seckill.bo.QueueMessage;
import com.qfedu.edu.seckill.bo.ReduceStock;
import com.qfedu.edu.seckill.exception.BusinessException;
import com.qfedu.edu.seckill.manager.RedisManager;
import com.qfedu.edu.seckill.po.StockStorage;
import com.qfedu.edu.seckill.po.StockStorageHistory;
import com.qfedu.edu.seckill.result.ResponseCode;
import com.qfedu.edu.seckill.storageservice.mapper.StockStorageHistoryMapper;
import com.qfedu.edu.seckill.storageservice.mapper.StockStorageMapper;
import com.qfedu.edu.seckill.storageservice.service.StockStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiaobobo
 * @since 2025-01-13
 */
@Service
@Slf4j
public class StockStorageServiceImpl extends ServiceImpl<StockStorageMapper, StockStorage> implements StockStorageService {

    @Autowired
    private StockStorageMapper stockStorageMapper;

    @Autowired
    private RedisManager redisManager;

    @Autowired
    private StockStorageHistoryMapper stockStorageHistoryMapper;

    @Override
    public int addStockStorage(String classId, Integer quantity) {
        //首先校验参数的合法性
        if(StringUtils.isEmpty(classId)||null==quantity){
            throw new BusinessException(ResponseCode.PARAM_EXCEPTION);
        }
        //执行到这里  说明参数无误
        //首先要通过商品id去判断库存表中是否有记录
        QueryWrapper<StockStorage> stockStorageQueryWrapper = new QueryWrapper<>();
        stockStorageQueryWrapper.eq("class_id",classId);
        StockStorage stockStorage = stockStorageMapper.selectOne(stockStorageQueryWrapper);
        int realQuantity=0;
        if(null==stockStorage){
            realQuantity= firstAdd(classId, quantity);
            log.info("第一次添加商品完成");
        }else{
            //说明这个商品已经添加过了
            realQuantity=havingHistoryAddClass(classId,quantity,stockStorage);
            log.info("历史添加商品完成");
        }
        return realQuantity;
    }

    @Override
    public void reduce(String reduceStockJson) {
        QueueMessage queueMessage = JSON.parseObject(reduceStockJson, QueueMessage.class);
        //先转换对象
        ReduceStock reduceStock = JSON.parseObject(queueMessage.getMessage(), ReduceStock.class);
        //然后拿到这个订单号
        String orderNumber = reduceStock.getOrderNumber();
        //拿到这个减库存的数量
        Integer num = reduceStock.getNum();
        //然后通过订单号去拿到这个订单信息
        String orderInfoJson = redisManager.getString(orderNumber);
        //转换成订单对象
        OrderShow orderShow = JSON.parseObject(orderInfoJson, OrderShow.class);
        String classId = orderShow.getClassId();
        //TODO 接下来编写减库存的逻辑
        //TODO 这里要添加分布式锁....
        //先向历史表中写入一条记录
        //通过classId去找到这个库存的id信息
        QueryWrapper<StockStorage> stockStorageQueryWrapper = new QueryWrapper<>();
        stockStorageQueryWrapper.eq("class_id",classId);
        StockStorage stockStorage = stockStorageMapper.selectOne(stockStorageQueryWrapper);
        if(null==stockStorage){
            //说明这个课程id有误
            log.error("课程id:{}有误无法去实现减库存!订单号是:{}--减库存的数量是:{}",classId,orderNumber,num);
            throw new BusinessException(ResponseCode.CLASS_ID_NOT_FOUND_EXCEPTION);
        }
        //执行到这里说明数据没有问题
        //拿到这个库存id信息
        String storageId = stockStorage.getStorageId();
        //构建库存的历史对象
        StockStorageHistory stockStorageHistory = new StockStorageHistory();
        stockStorageHistory.setStockStorageId(storageId);
        stockStorageHistory.setInQuanty(0);
        stockStorageHistory.setOutQuanty(num);
        stockStorageHistoryMapper.insert(stockStorageHistory);
        //在历史表中计算当前商品的真实库存
        Long actualStock = stockStorageHistoryMapper.caltureStockStorage(storageId);
        //接下来就可以去更新这个库存表中的数据了
        //首先要查询
        stockStorage.setQuanty(actualStock.intValue());
        stockStorageMapper.updateById(stockStorage);
        log.info("更新这个库存信息成功...");
    }

    /**
     * 有历史的课程库存的添加
     * @param classId
     * @param quantity
     */
    private int havingHistoryAddClass(String classId, Integer quantity,StockStorage stockStorage) {
        //首先要向历史表中写入记录
        //接下来向历史表中写入记录
        StockStorageHistory stockStorageHistory = new StockStorageHistory();
        stockStorageHistory.setStockStorageId(stockStorage.getStorageId());
        stockStorageHistory.setInQuanty(quantity);
        stockStorageHistory.setOutQuanty(0);
        stockStorageHistoryMapper.insert(stockStorageHistory);
        //然后进行真实库存的计算
        Long realQuantity=stockStorageHistoryMapper.caltureStockStorage(stockStorage.getStorageId());
        log.info("计算出来的真实库存是:{}",realQuantity);
        //去修改咋们的库存表中的库存信息
        UpdateWrapper<StockStorage> stockStorageUpdateWrapper = new UpdateWrapper<>();
        stockStorageUpdateWrapper.eq("storage_id",stockStorage.getStorageId());
        stockStorage.setQuanty(realQuantity.intValue());
        stockStorageMapper.update(stockStorage,stockStorageUpdateWrapper);
        return realQuantity.intValue();
    }

    /**
     * 第一次添加课程库存
     * @param classId
     * @param quantity
     */
    private int firstAdd(String classId, Integer quantity) {
        //说明这个商品是第一次添加
        //先向库存表中写入记录
        StockStorage stockStorage1 = new StockStorage();
        stockStorage1.setClassId(classId);
        stockStorage1.setQuanty(quantity);
        stockStorage1.setWareHourseId("1");
        stockStorageMapper.insert(stockStorage1);
        //接下来向历史表中写入记录
        StockStorageHistory stockStorageHistory = new StockStorageHistory();
        stockStorageHistory.setStockStorageId(stockStorage1.getStorageId());
        stockStorageHistory.setInQuanty(quantity);
        stockStorageHistory.setOutQuanty(0);
        stockStorageHistoryMapper.insert(stockStorageHistory);
        return quantity;
    }
}
